/* The sequential version with weak formulation */

#include "mycpxlib.h"

#define nloc 20
#define nclt 50


#include "mycpxutl.c"
#include "mycpxopt.c"
#include "mycpxcbfunc.c"


int
main (int argc, char *argv[])
{
   int i,j,ni, nj, idx = 0, idxR = 0;
   int flag = 0, status = 0;
   int nRows, nCols, nBins;
   double gap, bestobjval, tempobjval;
   int nodecnt, numfstbest, mipitercnt = 0;
   double t0, t1;
   double stepsize, startM;

   char logbuffer[50], data[100];
   // 
   MINFO myMinfo;
   int **bigmRowIdx = NULL;      // row indices of the big Ms
   int **bigmColIdx = NULL;      // colume indices           
   double **bigmVals = NULL;

   // Solution parameters
   double objval;
   double   *x     = NULL;
   CPXENVptr     env = NULL;
   CPXLPptr      lp = NULL;
   double *slack   = NULL;

   ni = nloc;
   nj = 1;
   stepsize = 0.05;
   startM = -.2;  //try different value here

   strcpy(data,argv[1]);

   printf("%d %d %f %f\n", ni, nj, startM, stepsize);
   printf("%s\n", data);

   set_seed(100,200); //set seed for Rmath random numbers

   /* Initialize the CPLEX environment */
   env = CPXopenCPLEX (&status);
   if ( env == NULL ) {
      char  errmsg[1024];
      fprintf (stderr, "Could not open CPLEX environment.\n");
      CPXgeterrorstring (env, status, errmsg);
      fprintf (stderr, "%s", errmsg);
      goto TERMINATE;
   }

   /* Setting mip options */
   status = DZturnoffpreproc(env);  if ( status )  goto TERMINATE;
   status = DZturnoffcuts(env);     if ( status )  goto TERMINATE;
   status = DZsetmipstrategy(env);  if ( status )  goto TERMINATE;
   status = DZsetmiplimits(env);    if ( status )  goto TERMINATE;
   //   status = DZsetmipoutput(env, logbuffer);    if ( status )  goto TERMINATE;
   status = CPXsetintparam (env, CPX_PARAM_SCRIND, CPX_OFF);

   /* Create the problem, using the filename as the problem name */
   lp = CPXcreateprob (env, &status, data);
   if ( lp == NULL ) {
      fprintf (stderr, "Failed to create LP.\n");
      goto TERMINATE;
   }

   status = CPXreadcopyprob (env, lp, data, NULL);
   if ( status ) {
      fprintf (stderr, "Failed to read and copy the problem data.\n");
      goto TERMINATE;
   }

   status = DZgetmipprobsize(env, lp, &nRows, &nCols, &nBins);
   if ( status )  goto TERMINATE;

   //   printf("nRows: %d  nCols: %d   nBins: %d \n", nRows, nCols, nBins);

   /* Allocate space for big M indices */
   bigmRowIdx = (int **) malloc(ni*sizeof(int *));
   bigmColIdx = (int **) malloc(ni*sizeof(int *));
   bigmVals =   (double **) malloc(ni*sizeof(double *));
   for(i = 0; i< ni; i++){
     bigmRowIdx[i] = (int *)malloc(nj*sizeof(int));
     bigmColIdx[i] = (int *)malloc(nj*sizeof(int));
     bigmVals[i]   = (double *)malloc(nj*sizeof(double));
   }
   /* Set the initial values of big M */
   for(i = 0; i< ni; i++){
     for(j=0; j<nj; j++)
       bigmVals[i][j] = startM;
   }

   /* Get the indices of big Ms in the A matrix, store 
      and check them */
   status = DZgetbigmindex(env, lp, ni, nj, bigmRowIdx, bigmColIdx);
   if ( status )  goto TERMINATE;

   /* Initialize cbhandle structure */
   myMinfo.flagPtr = &flag;
   myMinfo.ni = ni;
   myMinfo.nj = nj;
   myMinfo.bigmRowIdx = bigmRowIdx;
   myMinfo.bigmColIdx = bigmColIdx;
   myMinfo.bigmValsPtr     = &bigmVals;
   myMinfo.stepsize = stepsize;

   /* Set up MIP solve callbacks */
   status = CPXsetsolvecallbackfunc (env, usersetM, &myMinfo);
   /* Set up mip callbacks */
   status = CPXsetmipcallbackfunc (env, flagcallback, &myMinfo);

   /* Allocate space for solution and slackness */
   x = (double *) malloc (nCols*sizeof(double));
   slack = (double *) malloc (ni*sizeof(double));

   if ( x == NULL || slack == NULL) {
     fprintf (stderr, "No memory for solution values.\n");
     goto TERMINATE;
   }

   t0 = mysecond();    //Start the clock

   double tempx;

   /* Checking , changing coefficients and resolve */
   do{
     flag = 0;
     mipitercnt++;

     for(i=0; i<ni; i++){
       for(j=0; j<nj; j++){
	 //	 printf("%3.1f ", bigmVals[i][j]);
	 status = CPXchgcoef(env, lp, bigmRowIdx[i][j], bigmColIdx[i][j], bigmVals[i][j]);
       }
     }

     /* Optimize the problem and obtain the solution */
     status = CPXmipopt (env, lp);
     if ( status ) {
       fprintf (stderr,"Failed to optimize MIP.\n");
       goto TERMINATE;
     }

     status  = CPXgetmipobjval (env, lp, &objval);

     //Store the numfstbest
     if(objval != tempobjval){
       tempobjval = objval;
       numfstbest = mipitercnt;
     }

     status  = CPXgetbestobjval (env, lp, &bestobjval);
     if ( status ) {
       fprintf (stderr,"Failed to obtain objective value.\n");
       goto TERMINATE;
     }
     //     flag = 0; //make it iterate once
   }while(flag == 1);

   t1 = mysecond();     // End the clock 

   /* Report result */
   nodecnt = CPXgetnodecnt (env, lp);
   status  = CPXgetmipobjval (env, lp, &objval);
   if ( status ) {
     fprintf (stderr,"Failed to obtain objective value.\n");
     goto TERMINATE;
   }
   printf("The number of nodes is %d\n", nodecnt);
   printf("Number of iteration is %d\n", mipitercnt);
   printf("Solution is %f\n", objval);

   printf("Hello");

   /* Get the optimal solution */
   status = CPXgetmipx (env, lp, x, 0, nCols-1);
   if ( status ) {
     fprintf (stderr, "Failed to obtain solution.\n");
     goto TERMINATE;
   }

   /* Get the slackness of the constraints containg bigMs */
   status = CPXgetslack(env, lp, slack, bigmRowIdx[0][0], bigmRowIdx[ni-1][0]);
   if ( status ) {
     fprintf (stderr, "Failed to obtain solution.\n");
     goto TERMINATE;
   }

   for (j = 0; j < nCols; j++) {
   	  if( x[j] > 0 && x[j] < 0.000000001 ) x[j] = 0.0;
   }

   /* Print out formatted result to the output file */
   printf("big M values:\n");
   printf("obj: %f   best obj: %f  time: %f\n", objval, bestobjval, t1-t0);
   for(i = 0; i< ni; i++){
     for(j=0; j<nj; j++)
       printf("%5.3f ", bigmVals[i][j]);
   }
   printf("\n");
   printf("Y values: \n");
   for(i = 0; i< ni; i++){
     for(j=0; j<nj; j++)
       printf("%5.3f ", x[bigmColIdx[i][j]]);
   }
   printf("\n");
   printf("Slackness: \n");
   for(i = 0; i< ni; i++)
     printf("%5.3f ", slack[i]);
   printf("\n");
   //   printf("The optimizatio from process %d of %d running on %s takes %12.6f seconds.\n\n", myrank, p, name, t1-t0);   


TERMINATE:

   /* Free up the solution */
   free_and_null ((char **) &x);
   free_and_null ((char **) &slack);
   free_and_null ((char **) &bigmRowIdx);
   free_and_null ((char **) &bigmColIdx);
   free_and_null ((char **) &bigmVals);

   /* Free up the problem as allocated by CPXcreateprob, if necessary */
   if ( lp != NULL ) {
      status = CPXfreeprob (env, &lp);
      if ( status ) {
         fprintf (stderr, "CPXfreeprob failed, error code %d.\n", status);
      }
   }

   /* Free up the CPLEX environment, if necessary */
   if ( env != NULL ) {
      status = CPXcloseCPLEX (&env);
      if ( status ) {
      char  errmsg[1024];
         fprintf (stderr, "Could not close CPLEX environment.\n");
         CPXgeterrorstring (env, status, errmsg);
         fprintf (stderr, "%s", errmsg);
      }
   }

   return (status);

}  /* END main */




